package com.grayscale.core.config;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.grayscale.annotation.GrayScaleFunction;
import com.grayscale.core.constant.GrayScaleConstants;
import com.grayscale.core.util.GrayScalePathBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Map;

/**
 * 接口服务注册
 * 获取需要切量的服务 把所有方法和参数注册到zk
 * @author liuli
 * @date 2022/2/9
 */
@Configuration
public class GrayScaleServiceFunctionRegister implements ApplicationListener<ContextRefreshedEvent> {
    private Logger log = LoggerFactory.getLogger(this.getClass());

    @Resource
    GrayScaleClientConfig grayScaleClientConfig;
    @Resource
    GrayScaleZookeeper grayScaleZookeeper;

    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        if (!grayScaleClientConfig.needRegister()){
            return ;
        }
        try {
            if(contextRefreshedEvent.getApplicationContext().getParent()==null){
                Map<String,Object> beans = contextRefreshedEvent.getApplicationContext().getBeansWithAnnotation(Service.class);
                for (Object bean:beans.values()) {
                    String grayScaleService = getScaleClass(bean);
                    Class<?> aClass = Class.forName(grayScaleService);
                    Method[] methods = aClass.getDeclaredMethods();
                    for (Method m : methods){
                        // 只获取 public的方法  （过滤service中私有的方法）
                        if (m.getModifiers() == 1){
                            extracted(grayScaleService, m);
                        }
                    }
                }
           }
        } catch (Exception e) {
            log.error("注册切量服务异常{}",e);
        }
    }

    /***
     * 注册方法
      * @param grayScaleService
     * @param m
     * @throws Exception
     */
    private void extracted(String grayScaleService, Method m) throws Exception {
        // 有GrayScaleFunction注解的
        GrayScaleFunction grayScaleFunction = m.getAnnotation(GrayScaleFunction.class);
        if (null != grayScaleFunction) {
            String allFunctionName =grayScaleService +"#"+ m.getName();

            // 注册接口方法  可以配置的 应用服务#方法 （永久）
            String appServerPath = GrayScalePathBuilder.buildAppServerPathExt(grayScaleClientConfig.getAppName(),grayScaleClientConfig.getAppCode(), allFunctionName);
            grayScaleZookeeper.createPersistentNode(appServerPath, "",false);
            log.info("Register App-》【{}】 ServiceFunction-》【{}】",grayScaleClientConfig.getAppCode(), allFunctionName);
            //方法写入本地文件
           /* GrayScaleOfflineUtil.writeDisk(GrayScalePathBuilder.buildOfflineServerFunctionPath(grayScaleClientConfig,allFunctionName),"",false);
            log.info("WriteDisk App-》【{}】 ServiceFunction-》【{}】",grayScaleClientConfig.getAppCode(), allFunctionName);*/
            //注册参数 （节点和数据）
            String appServerParameterPath = GrayScalePathBuilder.buildAppServerPathExt(grayScaleClientConfig.getAppName(),grayScaleClientConfig.getAppCode(), allFunctionName+GrayScaleConstants.PARAMETERS);
            grayScaleZookeeper.createPersistentNode(appServerParameterPath, getPms(m),true);
            //log.info("Register ServiceFunction-》【{}】 Parameter-》【{}】",allFunctionName, getPms(m));
            //注册规则（节点）
            String appServerRulePath = GrayScalePathBuilder.buildAppServerPathExt(grayScaleClientConfig.getAppName(),grayScaleClientConfig.getAppCode(), allFunctionName+ GrayScaleConstants.RULES);
            grayScaleZookeeper.createPersistentNode(appServerRulePath, "",false);
            log.info("Register ServiceFunction-》【{}】 RulePath-》【{}】",allFunctionName, appServerRulePath);
        }
    }

    /***
     * 获取切量类
     * @param bean
     * @return
     */
    private String getScaleClass(Object bean) {
        String grayScaleService = bean.getClass().getName();
        if (grayScaleService.contains("$$EnhancerBySpringCGLIB")) {
            grayScaleService = grayScaleService.substring(0, grayScaleService.indexOf("$$EnhancerBySpringCGLIB"));
        }
        return grayScaleService;
    }

    /**
     * 获取方法参数  这里目前不支持 多级bean  TODO待扩展
     * @param m
     * @return
     */
    private String getPms(Method m) {
        StringBuilder sb = new StringBuilder();
        Parameter[] parameters = m.getParameters();
        for (int i = 0; i < parameters.length; i++) {
            String className = parameters[i].getParameterizedType().getTypeName();
            String detailS = "";
            try {
                Class clz = Class.forName(className);
                if (clz.getClassLoader()!= null){
                     detailS = "【对象属性"+JSONObject.toJSONString(clz.newInstance(), SerializerFeature.DisableCircularReferenceDetect, SerializerFeature.WriteMapNullValue)+"】";
                }
            } catch (Exception e) {
                log.error("parameters ClassNotFoundException");
            }
            if (i == parameters.length -1){
                sb.append(className +"  "+parameters[i].getName()+detailS);
            }else{
                sb.append(className +"  "+parameters[i].getName()+detailS);
                sb.append(",");
                sb.append("\n");
            }
        }
        return  sb.toString();
    }


}
